/* Copyright 2017 The Apollo Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "modules/map/hdmap/adapter/odr_parser/junctions_odr_parser.h"

#include <string>
#include <vector>

#include "tinyxml2/tinyxml2.h"

#include "modules/map/hdmap/adapter/xml_parser/common_define.h"
#include "modules/map/hdmap/adapter/xml_parser/status.h"
#include "modules/map/hdmap/adapter/xml_parser/util_xml_parser.h"

namespace apollo {
namespace hdmap {
namespace adapter {

Status JunctionsOdrParser::Parse(const tinyxml2::XMLElement& xml_node,
                                 std::map<std::string, Junction*>& junctions) {
  const tinyxml2::XMLElement* junction_node =
      xml_node.FirstChildElement("junction");
  while (junction_node) {
    // id
    Junction* junction = new Junction();
    int checker =
        UtilXmlParser::QueryStringAttribute(*junction_node, "id", &junction->id);
    if (checker != tinyxml2::XML_SUCCESS) {
      std::string err_msg = "Error parse junction id";
      return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
    }

    checker =
        UtilXmlParser::QueryStringAttribute(*junction_node, "name", &junction->name);
    if (checker != tinyxml2::XML_SUCCESS) {
      std::string err_msg = "Error parse junction name";
      return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
    }

    // connection 
    const tinyxml2::XMLElement* sub_node = junction_node->FirstChildElement("connection");
    while (sub_node) {
      Connection* con = new Connection();
      checker =
          UtilXmlParser::QueryStringAttribute(*sub_node, "id", &con->id);
      if (checker != tinyxml2::XML_SUCCESS) {
        std::string err_msg = "Error parse junction connection id";
        return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
      }

      checker =
          UtilXmlParser::QueryStringAttribute(*sub_node, "incomingRoad", &con->incomingRoad);
      if (checker != tinyxml2::XML_SUCCESS) {
        std::string err_msg = "Error parse junction connection incomingRoad";
        return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
      }

      checker =
          UtilXmlParser::QueryStringAttribute(*sub_node, "connectingRoad", &con->connectingRoad);
      if (checker != tinyxml2::XML_SUCCESS) {
        std::string err_msg = "Error parse junction connection connectingRoad";
        return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
      }

      std::string contactPoint;
      checker =
          UtilXmlParser::QueryStringAttribute(*sub_node, "contactPoint", &contactPoint);
      if (checker != tinyxml2::XML_SUCCESS) {
        std::string err_msg = "Error parse junction connection contactPoint";
        return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
      }
      if (contactPoint == "start") {
        con->contactPoint = START;
      } else if (contactPoint == "end") {
        con->contactPoint = END;
      } else {
        std::string err_msg = "Invalid parse junction connection contactPoint";
        return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
      }

      // lanelink
      const tinyxml2::XMLElement* lanelink_node = sub_node->FirstChildElement("laneLink");
      while (lanelink_node) {
        std::string from, to;
        checker =
            UtilXmlParser::QueryStringAttribute(*lanelink_node, "from", &from);
        if (checker != tinyxml2::XML_SUCCESS) {
          std::string err_msg = "Error parse lanelink from";
          return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
        }
        con->laneLinkFroms.push_back(from);
        
        checker =
            UtilXmlParser::QueryStringAttribute(*lanelink_node, "to", &to);
        if (checker != tinyxml2::XML_SUCCESS) {
          std::string err_msg = "Error parse lanelink to";
          return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);
        }
        con->laneLinkTos.push_back(to);
        lanelink_node = lanelink_node->NextSiblingElement("laneLink");
      }

      junction->connections.push_back(con);

      sub_node = sub_node->NextSiblingElement("connection");
    }

    junctions.insert(std::make_pair(junction->id, junction));
    junction_node = junction_node->NextSiblingElement("junction");
  }
  return Status::OK();
}

}  // namespace adapter
}  // namespace hdmap
}  // namespace apollo
